﻿using System.Collections.Generic;

namespace DataScripter.Excel.Formulas
{
    public class Operator : Formula
    {
        private static readonly Dictionary<string, int> OperatorPriorities;

        static Operator()
        {
            OperatorPriorities = new Dictionary<string, int>
                                      {
                                          {"<", 1},
                                          {"<=", 1},
                                          {">", 1},
                                          {">=", 1},
                                          {"+", 2},
                                          {"-", 2},
                                          {"*", 3},
                                          {"/", 3},
                                          {"^", 4},
                                      };
        }

        private static bool FirstOperatorHasHigherPriority(string operator1, string operator2)
        {
            int firstPriority = OperatorPriorities[operator1];
            int secondPriority = OperatorPriorities[operator2];
            return firstPriority > secondPriority;
        }

        class EqualsOperator : Operator
        {
            public EqualsOperator(Formula formula1, Formula formula2)
                : base(formula1, formula2, "=")
            { }
        }

        private readonly Formula _formula1;
        private readonly Formula _formula2;
        private readonly string _operation;

        public Operator(Formula formula1, Formula formula2, string operation)
        {
            _operation = operation;
            _formula1 = WithBracketsIfNecessary(formula1, operation);
            _formula2 = WithBracketsIfNecessary(formula2, operation);
        }

        public Operator(int i, Formula formula2, string operation)
            : this(new Value(i), formula2, operation)
        { }

        public Operator(Formula formula1, int i, string operation)
            : this(formula1, new Value(i), operation)
        { }

        public Operator(decimal d, Formula formula2, string operation)
            : this(new Value(d), formula2, operation)
        { }

        public Operator(Formula formula1, decimal d, string operation)
            : this(formula1, new Value(d), operation)
        { }

        private static Formula WithBracketsIfNecessary(Formula f, string operation)
        {
            Operator fOperator = f as Operator;
            if (fOperator != null)
            {
                if (FirstOperatorHasHigherPriority(operation, fOperator._operation))
                {
                    return new Brackets(f);
                }
            }
            return f;
        }

        #region Overrides of Formula

        public override string Resolve(ICell current)
        {
            return string.Format("{0}{1}{2}", _formula1.Resolve(current), _operation, _formula2.Resolve(current));
        }

        #endregion

        public override string ToString()
        {
            return _formula1 + _operation + _formula2;
        }
    }
}